package com.sdy.mvc.interceptor;

import com.sdy.mvc.utils.HttpUtil;
import com.sdy.common.utils.StringUtil;
import com.sdy.common.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by zzq on 2017/8/24.
 */
@Slf4j
@Component
public class ContextInterceptor extends HandlerInterceptorAdapter {
    
    private static ThreadLocal<Long> processStartTimeVariable = new ThreadLocal<>();
    private long reqSlowTime;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        processStartTimeVariable.set(System.currentTimeMillis());
        request.setCharacterEncoding("UTF-8");
        MDC.put("_ip", HttpUtil.getIpAddr(request));
        String uri = request.getRequestURI().replace(request.getContextPath(), "");
        if(!(handler instanceof HandlerMethod)) {
            return true;
        } else {
            HandlerMethod hm = (HandlerMethod)handler;
            log.info("[{} URI:{}] EXEC:{}.{}", request.getMethod(), uri, hm.getBeanType().getName(), hm.getMethod().getName());
            return true;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) throws Exception {
        request.setCharacterEncoding("UTF-8");
        if(null == mav) {
            this.processTime(request);
        } else {
            String viewName = mav.getViewName();
            log.info("{} to location :{}", StringUtil.startsWith(viewName, "redirect:")?"redirect":"forward", viewName);
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalUtil.clearRequestThreadLocal();
        this.processTime(request);
    }

    private void processTime(HttpServletRequest req) {
        Long start = processStartTimeVariable.get();
        if(null != start) {
            processStartTimeVariable.remove();
            long processTime = System.currentTimeMillis() - start;
            String uri = req.getRequestURI().replace(req.getContextPath(), "");
            if(processTime > this.getReqSlowTime()) {
                log.warn("[Process in {}: {} ms]", uri, processTime);
            } else {
                log.info("[Process in {}: {} ms]", uri, processTime);
            }

        }
    }

    private long getReqSlowTime() {
        if(0L == this.reqSlowTime) {
            this.reqSlowTime = 1500L;
        }

        return this.reqSlowTime;
    }

    public void setReqSlowTime(long reqSlowTime) {
        this.reqSlowTime = reqSlowTime;
    }

}
